home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 24 / Mac Magazin and MacEasy Magazine CD - Issue 24.iso / Online / clip2gif 0.7.2 / Calling clip2gif from C / example-cgi.c < prev    next >
Text File  |  1995-12-14  |  10KB  |  335 lines

  1. /*
  2.  *    Demo of using clip2gif with the CFM PPC
  3.  *
  4.  *    PLASE READ!
  5.  *
  6.  *    This CGI program returns a GIF showing the trajectory of a planar parallel robot.
  7.  *    If should be saved as robot.acgi. It can be called with the following URLs:
  8.  *
  9.  *    http://your.hostname/robot.acgi?k=h&w=5&h=7&n=10
  10.  *        -> html page wrapping an image of a robot with a motion of width 20 * w,
  11.  *                height 10 * h, and 2 * n intermediate positions
  12.  *                (each argument is coded in 1 char :-( )
  13.  *
  14.  *    http://your.hostname/robot.acgi?k=g&w=20&h=30&n=10
  15.  *        -> corresponding gif image 
  16.  *
  17.  *    To compile it, create a new PPC project with CW7 (other versions and compilers
  18.  *    might also work, but haven't been tested), include example-cgi.c, LoadClip2Gif.c,
  19.  *    InterfaceLib, MWCRuntime.Lib, MathLib and AppleScriptLib, and build it as "robot.acgi".
  20.  *    It should have at least canBackground and isHightLevelEventAware bits set. 
  21.  *    Copy it anywhere in the HTTP server document tree. clip2gif should be on the same
  22.  *    volume, or in the same folder if there are former versions on the same volume.
  23.  *
  24.  *    To quit robot.acgi, send it a quit AppleEvent ('tell app "robot.acgi" to quit'
  25.  *    in AppleScript), or type command-q.
  26.  *
  27.  ***  Warning:     The purpose of this CGI is *not* to show The Best Way to implement a CGI,
  28.  ***            but how simple it is to use clip2gif.
  29.  *
  30.  *    Copyright 1995, Yves Piguet. All rights reserved.
  31.  *
  32.  *    Can be distributed only as part of the whole clip2gif package.
  33.  *
  34.  *    If you use this source code, acknowledgment on your web pages would be appreciated.
  35.  *
  36.  *    Thanks!
  37.  */
  38.  
  39. #include <fp.h>    // math functions
  40. #include <AppleEvents.h>
  41.  
  42. #include "LoadClip2Gif.h"
  43.  
  44. int done;
  45.  
  46. static StringPtr http_html_header = "\pHTTP/1.0 200 OK\r\n\Content-type: text/html\r\n\r\n";
  47. static StringPtr http_gif_header = "\pHTTP/1.0 200 OK\r\nContent-type: image/gif\r\n\r\n";
  48. static StringPtr http_error = "\pHTTP/1.0 400 ERROR\r\n\r\n";
  49.  
  50. // HTML doc. Not that nice to have it here in pascal strings, but you'd been warned.
  51. // The inline image URL can become robot.acgi?k=h&w=2&h=3&k=g or even
  52. // robot.acgi?&k=g , but it still works.
  53.  
  54. static StringPtr html_t1 = "\p<html><header><title>Robot</title></header>\r\n<body><h1>Robot</h1>"
  55.                             "Planar parallel robot with horizontal tool base.<p>"
  56.                             "<img src=robot.acgi?";
  57. static StringPtr html_t2 =    "\p&k=g><p>\r\n"
  58.                             "<hr><h2>New Move</h2>"
  59.                             "<form action=robot.acgi method=get>\r\n"
  60.                             "<input type=hidden name=k value=h>\r\n"
  61.                             "Width: <select name=w>";
  62. static StringPtr html_t3 =    "\p<option value=1>20</option><option value=2>40</option>"
  63.                             "<option value=3>60</option><option value=4>80</option>\r\n"
  64.                             "<option value=5 selected>100</option><option value=6>120</option>"
  65.                             "<option value=7>140</option><option value=8>160</option>"
  66.                             "</select><p>\r\n";
  67. static StringPtr html_t4 =    "\pHeight: <select name=h>"
  68.                             "<option value=0>0</option><option value=1>10</option>"
  69.                             "<option value=2>20</option><option value=3>30</option>\r\n"
  70.                             "<option value=4 selected>40</option><option value=5>50</option>"
  71.                             "<option value=6>60</option><option value=7>70</option>";
  72. static StringPtr html_t5 =    "\p<option value=8>80</option>"
  73.                             "</select><p>\r\n"
  74.                             "Intermediate positions: <select name=n>\r\n"
  75.                             "<option value=0>0</option><option value=1>2</option>"
  76.                             "<option value=2>4</option><option value=4 selected>8</option>"
  77.                             "<option value=6>12</option><option value=9>18</option>";
  78. static StringPtr html_t6 =    "\p</select><p>\r\n"
  79.                             "<input type=submit value=Submit></form><p>\r\n"
  80.                             "<hr><address>CGI written by "
  81.                             "<a href=mailto:piguet@ia.epfl.ch>Yves Piguet</a></address>"
  82.                             "</body></html>\r\n";
  83.  
  84. // some geometric constants
  85.  
  86. #define iw 240
  87. #define ih 200
  88.  
  89. #define top 5
  90. #define ground 195
  91. #define center 120
  92. #define shoulder 20
  93. #define arm 105
  94. #define forearm 110
  95. #define paralw 10
  96.  
  97. static void InitToolbox()
  98. {
  99.     InitGraf((Ptr)&qd.thePort);
  100.     InitFonts();
  101.     InitWindows();
  102.     InitMenus();
  103.     TEInit();
  104.     InitDialogs(0L);
  105.     InitCursor();
  106. }
  107.  
  108. static pascal OSErr MyHandleQuit(AppleEvent *evt, AppleEvent *reply, long refCon)
  109. {
  110.     #pragma unused(evt, reply, refCon)
  111.     
  112.     done = 1;
  113.     return noErr;
  114. }
  115.  
  116. static void DrawRobot(short a, short b)
  117.     // draws the robot arms to point (a, b) over the ground
  118. {
  119.     double x, y, tmp, x1, y1;
  120.     short a1, b1;
  121.     
  122.     a1 = a - shoulder;
  123.     b1 = ground - top - b;
  124.     
  125.     tmp = a1 * a1 + b1 * b1;
  126.     x1 = (tmp + arm * arm - forearm * forearm) / (2 * tmp);
  127.     y1 = sqrt(arm * arm / tmp - x1 * x1);
  128.     
  129.     x = a1 * x1 - b1 * y1;
  130.     y = b1 * x1 + a1 * y1;
  131.     
  132.     MoveTo(center - shoulder, top);
  133.     Line((short)x, (short)y);
  134.     LineTo(center + a, ground - b);
  135.     Line(paralw, 0);
  136.     
  137.     MoveTo(center - shoulder + (short)x, top + (short)y);
  138.     Line(paralw, 0);
  139.     
  140.     MoveTo(center - shoulder + paralw, top);
  141.     Line((short)x, (short)y);
  142.     LineTo(center + a + paralw, ground - b);
  143.     
  144.     a1 = a + shoulder;
  145.     
  146.     tmp = a1 * a1 + b1 * b1;
  147.     x1 = (tmp + arm * arm - forearm * forearm) / (2 * tmp);
  148.     y1 = sqrt(arm * arm / tmp - x1 * x1);
  149.     
  150.     x = a1 * x1 + b1 * y1;
  151.     y = b1 * x1 - a1 * y1;
  152.     
  153.     MoveTo(center + shoulder + paralw, top);
  154.     Line((short)x, (short)y);
  155.     LineTo(center + a + paralw, ground - b);
  156. }
  157.  
  158. static pascal OSErr MyHandleSDOC(AppleEvent *evt, AppleEvent *reply, long refCon)
  159. {
  160.     #pragma unused(refCon)
  161.     
  162.     Offscreen os;
  163.     short width = 100, height = 40, n = 10, i;
  164.     unsigned char kind = 'h';
  165.     
  166.     DescType typeCode;
  167.     Size actualSize;
  168.     Str255 arg;
  169.     AEDesc replyStr;
  170.     Handle gifHandle;
  171.     OSErr err;
  172.     
  173.     err = AEGetParamPtr(evt, 'kfor', typeChar, &typeCode, (Ptr)(arg + 1), 250, &actualSize);
  174.     if (err != noErr)
  175.         goto oops;
  176.     arg[0] = actualSize;
  177.     
  178.     for (i = 0; i < arg[0] - 2; i++)
  179.         if (arg[i + 2] == '=')
  180.             switch (arg[i + 1])
  181.             {
  182.                 case 'k':
  183.                 case 'K':
  184.                     kind = arg[i + 3] | 32;        // lowercase
  185.                     if (kind != 'g')
  186.                         kind = 'h';
  187.                     arg[i + 2] = 'g';    // ready for the inline image URL
  188.                     break;
  189.                 case 'w':
  190.                 case 'W':
  191.                     if (arg[i + 3] >= '0' && arg[i + 3] <= '9')
  192.                         width = 20 * (arg[i + 3] - '0');
  193.                     else
  194.                         width = 100;
  195.                     break;
  196.                 case 'h':
  197.                 case 'H':
  198.                     if (arg[i + 3] >= '0' && arg[i + 3] <= '9')
  199.                         height = 10 * (arg[i + 3] - '0');
  200.                     else
  201.                         height = 40;
  202.                     break;
  203.                 case 'n':
  204.                 case 'N':
  205.                     if (arg[i + 3] >= '0' && arg[i + 3] <= '9')
  206.                         n = 2 * (arg[i + 3] - '0');
  207.                     else
  208.                         n = 8;
  209.                     break;
  210.             }
  211.     
  212.     if (kind == 'h')    // HTML
  213.     {
  214.         replyStr.descriptorType = typeChar;
  215.         err = PtrToHand((Ptr)(http_html_header + 1), &replyStr.dataHandle, http_html_header[0]);
  216.         err = PtrAndHand((Ptr)(html_t1 + 1), replyStr.dataHandle, html_t1[0]);
  217.         err = PtrAndHand((Ptr)(arg + 1), replyStr.dataHandle, arg[0]);    // part of gif URL
  218.         err = PtrAndHand((Ptr)(html_t2 + 1), replyStr.dataHandle, html_t2[0]);
  219.         err = PtrAndHand((Ptr)(html_t3 + 1), replyStr.dataHandle, html_t3[0]);
  220.         err = PtrAndHand((Ptr)(html_t4 + 1), replyStr.dataHandle, html_t4[0]);
  221.         err = PtrAndHand((Ptr)(html_t5 + 1), replyStr.dataHandle, html_t5[0]);
  222.         err = PtrAndHand((Ptr)(html_t6 + 1), replyStr.dataHandle, html_t6[0]);
  223.     }
  224.     else                // GIF
  225.     {
  226.         err = BeginOffscreen(&os, iw, ih, 4, colorPaletteSystem);
  227.         if (err != noErr)
  228.             goto oops;
  229.         
  230.         // now the QuickDraw port is ok; we can draw directly
  231.         
  232.         PenSize(2, 2);
  233.         
  234.         // arms in the intermediate positions
  235.         
  236.         ForeColor(cyanColor);
  237.         for (i = 1; i <= n; i++)
  238.             DrawRobot(-width / 2 + width * i / (n + 1), height * i / (n + 1));
  239.         
  240.         // arms in the extreme positions
  241.         
  242.         ForeColor(blackColor);
  243.         DrawRobot(-width / 2, 0);
  244.         DrawRobot(width / 2, height);
  245.                 
  246.         // top (where the robot is fixed)
  247.         
  248.         ForeColor(redColor);
  249.         PenSize(4, 4);
  250.         MoveTo(0, top);
  251.         Line(iw, 0);
  252.         PenSize(1, 1);
  253.         
  254.         // that's it!
  255.                 
  256. //#ifdef noooooh
  257.         {
  258.             // if you want to check the image before launching your http server,
  259.             // enable these lines and send robot.acgi the following AS command:
  260.             // «event WWWΩsdoc» given «class kfor»:"k=g&w=5&h=5&n=5"
  261.             
  262.             FSSpec spec;
  263.             FSMakeFSSpec(0, 0, "\ptest.gif", &spec);
  264.             (void)ConvertPixmapToGIFFile(os.pixmap, &spec, 1, transparencyFirstPixel);
  265.         }
  266. //#endif
  267.         
  268.         err = ConvertPixmapToGIFHandle(os.pixmap, &gifHandle, 1, transparencyFirstPixel);
  269.         
  270.         if (err == noErr)    // concat. the http GIF header and the gif
  271.         {
  272.             replyStr.descriptorType = typeChar;
  273.             err = PtrToHand((Ptr)(http_gif_header + 1), &replyStr.dataHandle, http_gif_header[0]);
  274.             err = HandAndHand(gifHandle, replyStr.dataHandle);
  275.             DisposHandle(gifHandle);
  276.         }
  277.         
  278.         (void)DisposeOffscreen(&os);
  279.     }
  280.     
  281. oops:
  282.     if (err != noErr)
  283.     {
  284.         replyStr.descriptorType = typeChar;
  285.         err = PtrToHand((Ptr)(http_error + 1), &replyStr.dataHandle, http_error[0]);
  286.     }
  287.     
  288.     (void)AEPutParamDesc(reply, keyDirectObject, &replyStr);
  289.     DisposHandle(replyStr.dataHandle);
  290.     
  291.     return noErr;
  292. }
  293.  
  294. void main(void)
  295. {
  296.     EventRecord myEvent;
  297.     OSErr err;
  298.     
  299.     InitToolbox();    // standard stuff
  300.     
  301.     // uses the CFM to gain access to clip2gif exported functions
  302.     
  303.     err = LoadClip2Gif();
  304.     if (err != noErr)
  305.     {
  306.         SysBeep(1);    // Cannot load clip2gif
  307.         return;
  308.     }
  309.     
  310.     // installs AppleEvent handlers for quit and sdoc
  311.     
  312.     (void)AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
  313.             NewAEEventHandlerProc(MyHandleQuit), 0L, 0);
  314.     (void)AEInstallEventHandler('WWWΩ', 'sdoc',
  315.             NewAEEventHandlerProc(MyHandleSDOC), 0L, 0);
  316.     
  317.     // main event loop
  318.     
  319.     for (done = 0; !done;)
  320.     {
  321.         WaitNextEvent(everyEvent, &myEvent, 30L, 0L);
  322.         switch (myEvent.what)
  323.         {
  324.             case keyDown:
  325.                 if (myEvent.modifiers & cmdKey
  326.                         && (myEvent.message & charCodeMask) == 'q')    // command-q -> quit
  327.                     done = 1;
  328.                 break;
  329.             case kHighLevelEvent:
  330.                 (void)AEProcessAppleEvent(&myEvent);
  331.                 break;
  332.         }
  333.     }
  334. }
  335.